package top.ffhome.system.controller;

import cn.hutool.core.collection.CollUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import top.ffhome.common.result.Result;
import top.ffhome.system.entity.SysDoc;
import top.ffhome.system.service.SysDocService;
import top.ffhome.util.file.FileUtils;

import java.io.File;
import java.io.IOException;
import java.math.BigInteger;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.nio.file.attribute.PosixFilePermission;
import java.security.MessageDigest;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

@CrossOrigin
@RestController
@RequestMapping("api")
@Slf4j
@Api(tags = "上传文件控制器")
public class SysUploadController {
    @Autowired
    private SysDocService docService;
    @Value(value = "${ffhome.resource-location:}")
    private String resourceLocation;
    @Value(value = "${ffhome.upload-domain:}")
    private String uploadDomain;

    private List<String> types = CollUtil.newArrayList("jpg", "png", "gif", "doc", "docx", "xls", "xlsx", "ppt", "pptx",
            "pdf");

    @RequiresPermissions("system:file:upload")
    @PostMapping("/upload")
    @ApiOperation("上传文件接口")
    public Result upload(MultipartFile file) throws Exception {
        // 检查文件类型并重命名
        String fileName = FileUtils.getFileNameByType(file.getOriginalFilename(), types);
        if (fileName == null) {
            return Result.fail(-1, "文件类型不正确");
        }

        String md5 = getFileMD5(file);
        SysDoc search = docService.getByMd5(md5);
        boolean newDir = false;
        if (search != null) {
            return Result.success(convertToResult(search));
        }

        // 上传文件
        File imageFolder = new File(resourceLocation);
        File f = new File(imageFolder, fileName);
        if (!f.getParentFile().exists()) {
            f.getParentFile().mkdirs();
            newDir = true;
        }
        try {
            file.transferTo(f);
            storeFile(f, newDir);
            SysDoc doc = new SysDoc();
            doc.setMd5(md5);
            doc.setPath(fileName);
            docService.insert(doc);
            return Result.success(convertToResult(doc));
        } catch (IOException e) {
            return Result.fail(e.getMessage());
        }
    }

    private SysDoc convertToResult(SysDoc doc) {
        doc.setUrl(uploadDomain + doc.getPath());
        doc.setMd5(null);
        return doc;
    }

    private static String getFileMD5(MultipartFile file) {
        try {
            byte[] uploadBytes = file.getBytes();
            MessageDigest md5 = MessageDigest.getInstance("MD5");
            byte[] digest = md5.digest(uploadBytes);
            String hashString = new BigInteger(1, digest).toString(16);
            return hashString;
        } catch (Exception e) {
            log.warn(e.getMessage(), e);
        }
        return "";
    }

    private static void storeFile(File file, boolean newDir) throws IllegalStateException, IOException {
        // 设置权限
        Set<PosixFilePermission> perms = new HashSet<PosixFilePermission>();
        perms.add(PosixFilePermission.OWNER_READ);// 设置所有者的读取权限
        perms.add(PosixFilePermission.OWNER_WRITE);// 设置所有者的写权限
        perms.add(PosixFilePermission.OWNER_EXECUTE);// 设置所有者的执行权限
        perms.add(PosixFilePermission.GROUP_READ);// 设置组的读取权限
        perms.add(PosixFilePermission.GROUP_EXECUTE);// 设置组的执行权限
        perms.add(PosixFilePermission.OTHERS_READ);// 设置其他的读取权限
        perms.add(PosixFilePermission.OTHERS_EXECUTE);// 设置其他的执行权限
        try {
            Files.setPosixFilePermissions(Paths.get(file.getAbsolutePath()), perms);// 修改图片文件的权限
            if (newDir) {
                for (int i = 0; i < 3; i++) {
                    file = file.getParentFile();
                    Files.setPosixFilePermissions(Paths.get(file.getAbsolutePath()), perms);// 修改文件夹路径的权限
                }
            }
        } catch (Exception e) {
        }
    }
}
